﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Tea.Parser {
    public abstract class AstVisitor :IAstVisitor {

        protected virtual void VisitExpression(Expression node) {
            node.Accept(this);
        }

        protected virtual void VisitStatement(Statement node) {
            node.Accept(this);
        }

        protected void VisitNodeList<T>(NodeList<T> node)
            where T :Node {
            foreach(T cnode in node)
                cnode.Accept(this);
        }

        public virtual void VisitArrayLiteral(ArrayLiteral arrayLiteral) {
            VisitNodeList(arrayLiteral.Values);
        }

        public virtual void VisitAssignmentExpression(AssignmentExpression assignmentExpression) {
            VisitExpression(assignmentExpression.Target);
            VisitExpression(assignmentExpression.Value);
        }

        public virtual void VisitBinaryExpression(BinaryExpression binaryExpression) {
            VisitExpression(binaryExpression.Left);
            VisitExpression(binaryExpression.Right);
        }

        public virtual void VisitBlock(Block blockStatement) {
            VisitNodeList(blockStatement.Statements);
        }

        public virtual void VisitBreakStatement(BreakStatement breakStatement) {
            if (breakStatement.Target != null)
                VisitStatement(breakStatement.Target);
        }

        public virtual void VisitCallNative(CallNative callNative) {

        }

        public virtual void VisitCaseClause(CaseClause caseLabel) {
            VisitExpression(caseLabel.Label);
        }

        public virtual void VisitConditionalExpression(ConditionalExpression conditionalExpression) {
            VisitExpression(conditionalExpression.Condition);
            VisitExpression(conditionalExpression.ThenExpression);
            VisitExpression(conditionalExpression.ElseExpression);
        }

        public virtual void VisitContinueStatement(ContinueStatement continueStatement) {
            VisitStatement(continueStatement.Target);
        }

        public virtual void VisitPostfixExpression(PostfixExpression countOperation) {
            
        }

        public virtual void VisitConstStatement(ConstStatement constStatement) {
            VisitNodeList(constStatement.Variables);
        }

        public virtual void VisitDebuggerStatement(DebuggerStatement debuggerStatement) {
            
        }

        public virtual void VisitDoWhileStatement(DoWhileStatement doWhileStatement) {
            VisitExpression(doWhileStatement.Condition);
            VisitStatement(doWhileStatement.Body);
        }

        public virtual void VisitEmptyStatement(EmptyStatement emptyStatement) {
            
        }

        public virtual void VisitExpressionStatement(ExpressionStatement expressionStatement) {
            VisitExpression(expressionStatement.Expression);
        }

        public virtual void VisitFalseLiteral(FalseLiteral falseLiteral) {
            
        }

        public virtual void VisitForInStatement(ForInStatement forinStatement) {
            VisitStatement(forinStatement.Each);
            VisitExpression(forinStatement.Enumerable);
            VisitStatement(forinStatement.Body);
        }

        public virtual void VisitForStatement(ForStatement forStatement) {
            VisitStatement(forStatement.InitStatement);
            VisitExpression(forStatement.NextExpression);
            VisitExpression(forStatement.NextExpression);
            VisitStatement(forStatement.Body);
        }

        public virtual void VisitFunctionExpression(FunctionExpression functionExpression) {
            VisitNodeList(functionExpression.Statements);
        }

        public virtual void VisitLabelledStatement(LabelledStatement labelledStatement) {

        }

        public virtual void VisitFunctionCallExpression(FunctionCallExpression functionCallExpression) {
            VisitExpression(functionCallExpression.Target);
            VisitNodeList < Expression>(functionCallExpression.Arguments);
        }

        public virtual void VisitFunctionDeclaration(FunctionDeclaration functionDeclaration) {
            VisitFunctionExpression(functionDeclaration.Function);
        }

        public virtual void VisitNewExpression(NewExpression newExpression) {
            VisitExpression(newExpression.Expression);
        }

        public virtual void VisitNumberLiteral(NumberLiteral numberLiteral) {
            
        }

        public virtual void VisitNullLiteral(NullLiteral nullLiteral) {
            
        }

        public virtual void VisitIdentifier(Identifier identifier) {
            
        }

        public virtual void VisitIfStatement(IfStatement ifStatement) {
            VisitExpression(ifStatement.Condition);
            VisitStatement(ifStatement.Then);
            VisitStatement(ifStatement.Else);
        }

        public virtual void VisitIncrementOperation(IncrementOperation incrementOperation) {
            
        }

        public virtual void VisitObjectLiteral(ObjectLiteral objectLiteral) {
            
        }

        public virtual void VisitParamedExpression(ParamedExpression paramedExpression) {
            VisitExpression(paramedExpression.Expression);
        }

        public virtual void VisitPropertyCallExpression(PropertyCallExpression propertyCallExpression) {
            VisitExpression(propertyCallExpression.Target);
        }

        public virtual void VisitRegExpLiteral(RegExpLiteral regExpLiteral) {
            
        }

        public virtual void VisitReturnStatement(ReturnStatement returnStatement) {
            VisitExpression(returnStatement.Expression);
        }

        public virtual void VisitSemicolon(Semicolon semicolon) {
            
        }

        public virtual void VisitStringLiteral(StringLiteral stringLiteral) {
            
        }

        public virtual void VisitSwitchStatement(SwitchStatement switchStatement) {
            VisitExpression(switchStatement.Condition);
            VisitNodeList(switchStatement.Cases);
        }

        public virtual void VisitThisLiteral(ThisLiteral thisLiteral) {
            
        }

        public virtual void VisitThrowStatement(ThrowStatement throwStatement) {
            VisitExpression(throwStatement.Expression);
        }

        public virtual void VisitTrueLiteral(TrueLiteral trueLiteral) {
            
        }

        public virtual void VisitTryCatchFinallyStatement(TryCatchFinallyStatement tryCatchFinallyStatement) {
            VisitBlock(tryCatchFinallyStatement.TryBlock);
            VisitBlock(tryCatchFinallyStatement.CatchBlock);
            VisitBlock(tryCatchFinallyStatement.FinallyBlock);
        }

        public virtual void VisitTryCatchStatement(TryCatchStatement tryCatchStatement) {
            VisitBlock(tryCatchStatement.TryBlock);
            VisitBlock(tryCatchStatement.CatchBlock);
        }

        public virtual void VisitTryFinallyStatement(TryFinallyStatement tryFinallyStatement) {
            VisitBlock(tryFinallyStatement.TryBlock);
            VisitBlock(tryFinallyStatement.FinallyBlock);
        }

        public virtual void VisitUndefinedExpression(UndefinedExpression undefinedExpression) {
            
        }

        public virtual void VisitUnaryExpression(UnaryExpression unaryExpression) {
            VisitExpression(unaryExpression.Expression);
        }

        public virtual void VisitVariableDeclaration(VariableDeclaration variableDeclaration) {
            VisitExpression(variableDeclaration.Initialiser);
        }

        public virtual void VisitVariableStatement(VariableStatement variableStatement) {
            VisitNodeList(variableStatement.Variables);
        }

        public virtual void VisitWhileStatement(WhileStatement whileStatement) {
            VisitExpression(whileStatement.Condition);
            VisitStatement(whileStatement.Body);
        }

        public virtual void VisitWithStatement(WithStatement withStatement) {
            VisitStatement(withStatement.Body);
        }


        public virtual void VisitIndexCallExpression(IndexCallExpression indexCallExpression) {
            VisitExpression(indexCallExpression.Target);
            VisitExpression(indexCallExpression.Argument);
        }

        public virtual void VisitProperty(ObjectLiteral.Property property) {
            VisitExpression(property.Value);
        }


        public virtual void VisitAdditiveExpression(AdditiveExpression additiveExpression) {
            VisitExpression((BinaryExpression)additiveExpression);
        }

        public virtual void VisitMultiplicativeExpression(MultiplicativeExpression multiplicativeExpression) {
            VisitExpression((BinaryExpression)multiplicativeExpression);
        }

        public virtual void VisitShiftExpression(ShiftExpression shiftExpression) {
            VisitExpression((BinaryExpression)shiftExpression);
        }

        public virtual void VisitRelationalExpression(RelationalExpression relationalExpression) {
            VisitExpression((BinaryExpression)relationalExpression);
        }

        public virtual void VisitEqualityExpression(EqualityExpression equalityExpression) {
            VisitExpression((BinaryExpression)equalityExpression);
        }

        public virtual void VisitBitwiseExpression(BitwiseExpression bitwiseExpression) {
            VisitExpression((BinaryExpression)bitwiseExpression);
        }

        public virtual void VisitLogicalExpression(LogicalExpression logicalExpression) {
            VisitExpression((BinaryExpression)logicalExpression);
        }

        public virtual void VisitCommaExpression(CommaExpression commaExpression) {
            VisitExpression((BinaryExpression)commaExpression);
        }

        public virtual void VisitUserDefinedOperatorExpression(UserDefinedOperatorExpression userDefinedOperatorExpression) {
            VisitExpression((BinaryExpression)userDefinedOperatorExpression);
        }


        public void VisitModule(Module module) {
            throw new NotImplementedException();
        }
    }
}
